#region Disclaimer; Copyright (c) Amit Bhandari, 2007)
/******
 * This document is part of xtremeCC library.
 * 
 * xtremeCC is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, version 3 of the License.
 * 
 * xtremeCC is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with xtremeCC library.  If not, see <http://www.gnu.org/licenses/>.
 ********/
#endregion

#region Namespaces
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using System.ComponentModel;

using xtremeCC.Common;
#endregion

namespace xtremeCC.Label
{
	/// <summary>
	/// xtremeLabel derives from System.Windows.Forms.Control class.
	/// <para>
	///	xtremeLabel is a label control for Windows Forms 2.0
	/// </para>
	/// </summary>
	public class xtremeLabel : Control
	{
		#region Default constructor and Dispose
		/// <summary>
		/// Default constructore for xtremeLabel control.
		/// </summary>
		public xtremeLabel()
		{
			//set the control styles
			//---------------------------------------------------------------
			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
			SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
			SetStyle(ControlStyles.ResizeRedraw, true);
			SetStyle(ControlStyles.SupportsTransparentBackColor, true);
			SetStyle(ControlStyles.UserPaint, true);
			//----------------------------------------------------------------

			//initialize the instance
			//this.Name = "xtremeLabel";
			this.Text = this.Name;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				//if (components != null)
				//    components.Dispose();
			}
			base.Dispose(disposing);
		}
		#endregion
		#region Design-time properties

		#region BackgroundColorStyle

		private BackColorStyle _backgroundColorStyle = BackColorStyle.None;		
		/// <summary>
		/// Get/Set the background color style of the control. The various options are
		/// <list type="bullet">
		/// <item>Single Color (BackColor property will be used to paint the background of control).</item>
		/// <item>Vertical Gradient Color</item>
		/// <item>Horizontal Gradient Color</item>
		/// <item>Diagonal Gradient Color</item>
		/// </list>
		/// </summary>
		[Description("Tells whether the background color of control has to be rendered as gradient or not.")]
		[Category("xtremeAppearance")]
		[DefaultValue(BackColorStyle.None)]
		public BackColorStyle BackgroundColorStyle
		{
			get
			{
				return _backgroundColorStyle;
			}
			set
			{
				if (value != _backgroundColorStyle)
					_backgroundColorStyle = value;

				Invalidate();
			}
		}

		#endregion
		#region User specified BackColor

		private Color _userBackColor1= Color.FromKnownColor(KnownColor.Control);
		private Color _userBackColor2= Color.FromKnownColor(KnownColor.Control);
		/// <summary>
		/// Gets/Sets the starting color for the background gradient color vector.
		/// </summary>
		[Description("Starting color for the background gradient vector.")]
		[Category("xtremeAppearance")]
		[DefaultValue(KnownColor.Control)]
		public Color UserBackColor1
		{
			get
			{
				return _userBackColor1;
			}
			set
			{
				if (value != _userBackColor1)
					_userBackColor1 = value;

				if(BackgroundColorStyle != BackColorStyle.None)
					Invalidate();
			}
		}

		/// <summary>
		/// Gets/Sets the ending color for the background gradient color vector.
		/// </summary>
		[Description("Ending color for the background gradient vector.")]
		[Category("xtremeAppearance")]
		[DefaultValue(KnownColor.Control)]
		public Color UserBackColor2
		{
			get
			{
				return _userBackColor2;
			}
			set
			{
				if (value != _userBackColor2)
					_userBackColor2 = value;

				if (BackgroundColorStyle != BackColorStyle.None)
					Invalidate();
			}
		} 

		#endregion
		#region IconStyles

		private IconDisplayPosition _iconDisplayStyle = IconDisplayPosition.LeftMiddle;
		/// <summary>
		/// Gets/Sets the display position of icon.
		/// </summary>
		[Description("Position of display of icon, if selected.")]
		[Category("xtremeAppearance")]
		[DefaultValue(IconDisplayPosition.LeftMiddle)]
		public IconDisplayPosition IconDisplayStyle
		{
			get
			{
				return _iconDisplayStyle;
			}
			set
			{
				if (value != _iconDisplayStyle)
					_iconDisplayStyle = value;
			}
		}

		private IconEffects _iconEffects = IconEffects.None;
		/// <summary>
		/// Gets/Sets the effects to be applied on the icon.
		/// </summary>
		[Description("Effects to be applied on the icon selected, blur or zoom effect")]
		[Category("xtremeAppearance")]
		[DefaultValue(IconEffects.None)]
		public IconEffects IconEffects
		{
			get
			{
				return _iconEffects;
			}
			set
			{
				if (value != _iconEffects)
					_iconEffects = value;
			}
		}

		private float _iconBlurFactor = 0.1f;
		/// <summary>
		/// Gets/Sets the blur factor to be applied on the icon.
		/// </summary>
		[Description("Blur factor to be applied on the icon image.")]
		[Category("xtremeAppearance")]
		[DefaultValue(0.1f)]
		public float IconBlurFactor
		{
			get
			{
				return _iconBlurFactor;
			}
			set
			{
				if (value > 1.0)
					_iconBlurFactor = 1.0f;
				else if (value < 0.0)
					_iconBlurFactor = 0.0f;
				else if (value != _iconBlurFactor)
					_iconBlurFactor = value;
			}
		}

		private short _iconZoomFactor = 1;
		/// <summary>
		/// Gets/Sets the zoom factor to be applied on the icon.
		/// </summary>
		[Description("Zoom factor to be applied on the icon image.")]
		[Category("xtremeAppearance")]
		[DefaultValue(1)]
		public short IconZoomFactor
		{
			get
			{
				return _iconZoomFactor;
			}
			set
			{
				if (value != _iconZoomFactor)
					_iconZoomFactor = value;
			}
		}

		private Bitmap _icon = null;
		/// <summary>
		/// The icon display image to be used.
		/// </summary>
		[Description("Icon image to be displayed on the control.")]
		[Category("xtremeAppearance")]
		public Bitmap Icon
		{
			get
			{
				return _icon;
			}
			set
			{
				if (value != _icon && value != null)
					_icon = value;
			}
		} 

		#endregion
		#region ShadowStyle

		private ShadowStyle _shadow = ShadowStyle.NoShadow;
		/// <summary>
		/// Enables/Disables the Shadow for Label control or text or both.
		/// </summary>
		[Description("Enables/Disables the shadow for control.")]
		[Category("xtremeAppearance")]
		[DefaultValue(ShadowStyle.NoShadow)]
		public ShadowStyle Shadow
		{
			get
			{
				return _shadow;
			}
			set
			{
				if (value != _shadow)
					_shadow = value;

				Invalidate();
			}
		}

		private int _shadowOffset = 3;
		/// <summary>
		/// Gets/Sets the offset of shadow from actual control/text
		/// </summary>
		[Description("Gets/Sets the offset for shadows.")]
		[Category("xtremeAppearance")]
		[DefaultValue(2)]
		public int ShadowOffset
		{
			get
			{
				return _shadowOffset;
			}
			set
			{
				if (value != _shadowOffset)
					_shadowOffset = value;

				Invalidate();
			}
		}

		private Color _shadowColor = Color.DimGray;
		/// <summary>
		/// Gets/Sets the shadow color of control.
		/// </summary>
		[Description("Sets the color for shadow.")]
		[Category("xtremeAppearance")]
		[DefaultValue(KnownColor.Gray)]
		public Color ShadowColor
		{
			get
			{
				return _shadowColor;
			}
			set
			{
				if (value != _shadowColor)
					_shadowColor = value;

				Invalidate();
			}
		}

		#endregion
		#region TextAppearance

		private Point _textLocation = new Point(10, 20);
		/// <summary>
		/// Gets/Sets the location of text on control.
		/// </summary>
		[Description("Sets the location of text to be displayed on control")]
		[Category("xtremeAppearance")]
		public Point TextLocation
		{
			get
			{
				return _textLocation;
			}
			set
			{
				if (value != _textLocation)
					_textLocation = value;
			}
		}

		private bool _renderAntiAliasText = false;
		/// <summary>
		/// Enables/Disables the Anti-alias rendering for control text.
		/// </summary>
		[Description("Enables/Disables the anti-alias rendering of text on the control.")]
		[Category("xtremeAppearance")]
		[DefaultValue(false)]
		public bool RenderAntiAlias
		{
			get
			{
				return _renderAntiAliasText;
			}
			set
			{
				if (value != _renderAntiAliasText)
				{
					_renderAntiAliasText = value;
					Invalidate();
				}
			}
		}


		private Color _textForeColor1 = Color.FromKnownColor(KnownColor.ControlText);
		private Color _textForeColor2 = Color.FromKnownColor(KnownColor.ControlText);
		/// <summary>
		/// Gets/Sets the starting color for gradient color vector for control text.
		/// </summary>
		[Description("Starting color for fore-color gradient vector.")]
		[Category("xtremeAppearance")]
		[DefaultValue(KnownColor.ControlText)]
		public Color UserForeColor1
		{
			get
			{
				return _textForeColor1;
			}
			set
			{
				if (value != _textForeColor1)
					_textForeColor1 = value;

				if (TextColorStyle != ForeColorStyle.None)
					Invalidate();
			}
		}

		/// <summary>
		/// Gets/Sets the ending color for gradient color vector for control text.
		/// </summary>
		[Description("Ending color for fore-color gradient vector.")]
		[Category("xtremeAppearance")]
		[DefaultValue(KnownColor.ControlText)]
		public Color UserForeColor2
		{
			get
			{
				return _textForeColor2;
			}
			set
			{
				if (value != _textForeColor2)
					_textForeColor2 = value;

				if (TextColorStyle != ForeColorStyle.None)
					Invalidate();
			}
		}

		private ForeColorStyle _foreColorStyle = ForeColorStyle.None;
		/// <summary>
		/// 
		/// </summary>
		[Description("Tells whether the fore-color of control has to be rendered as gradient or not.")]
		[Category("xtremeAppearance")]
		[DefaultValue(ForeColorStyle.None)]
		public ForeColorStyle TextColorStyle
		{
			get
			{
				return _foreColorStyle;
			}
			set
			{
				if (value != _foreColorStyle)
					_foreColorStyle = value;

				Invalidate();
			}
		}

		/// <summary>
		/// Gets/Sets the control text
		/// </summary>
		[Category("xtremeAppearance")]
		public override string Text
		{
			get
			{
				return base.Text;
			}
			set
			{
				base.Text = value;
				Invalidate();
			}
		} 

		#endregion

		#endregion
		#region Paint Method

		/// <summary>
		/// Controls paint method. All painting is done here.
		/// </summary>
		/// <param name="e">Object of PaintEventArgs, contains a reference of Graphics object
		/// on which drawing will take place.</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			//base.OnPaint(e);
			if (RenderAntiAlias == true)
				e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
			else
				e.Graphics.SmoothingMode = SmoothingMode.None;

			#region Shadow and background painiting

			//Shadow idea taken from
			//http://www.openwinforms.com/creating_cool_gradient_panel_gdi.html

			Rectangle rectFull = new Rectangle(0, 0, this.Width, this.Height);
			Rectangle rectLessOffset = new Rectangle(0, 0,
					this.Width - ShadowOffset, this.Height - ShadowOffset);

			if (Shadow == ShadowStyle.ControlShadow || Shadow == ShadowStyle.BothShadows)
			{
				GraphicsPath graphPathShadow = GetPath(rectFull);

				using (PathGradientBrush gBrush = new PathGradientBrush(graphPathShadow))
				{
					gBrush.WrapMode = WrapMode.Clamp;
					ColorBlend colorBlend = new ColorBlend(3);
					colorBlend.Colors = new Color[]{Color.Transparent,
			                Color.FromArgb(180, ShadowColor),
			                Color.FromArgb(180, ShadowColor)};
					colorBlend.Positions = new float[] { 0f, .1f, 1f };
					gBrush.InterpolationColors = colorBlend;
					e.Graphics.FillPath(gBrush, graphPathShadow);
				};

				#region Background color painting

				// painting background first
				if (BackgroundColorStyle == BackColorStyle.None)
				{
					using (SolidBrush br = new SolidBrush(this.BackColor))
					{
						e.Graphics.FillRectangle(br, rectLessOffset);
					};
				}
				else if (BackgroundColorStyle == BackColorStyle.HorizontalGradient)
				{
					using (LinearGradientBrush lgb = new LinearGradientBrush(
						rectLessOffset, UserBackColor1, UserBackColor2, 0f))
					{
						e.Graphics.FillRectangle(lgb, rectLessOffset);
					};
				}
				else if (BackgroundColorStyle == BackColorStyle.VerticalGradient)
				{
					using (LinearGradientBrush lgb = new LinearGradientBrush(
						rectLessOffset, UserBackColor1, UserBackColor2, 90f))
					{
						e.Graphics.FillRectangle(lgb, rectLessOffset);
					};
				}
				else if (BackgroundColorStyle == BackColorStyle.DiagonalGradient)
				{
					using (LinearGradientBrush lgb = new LinearGradientBrush(
						rectLessOffset, UserBackColor1, UserBackColor2, 45f))
					{
						e.Graphics.FillRectangle(lgb, rectLessOffset);
					};
				}

				#endregion
			}
			else
			{
				#region Background color painting

				// painting background first
				if (BackgroundColorStyle == BackColorStyle.None)
				{
					using (SolidBrush br = new SolidBrush(this.BackColor))
					{
						e.Graphics.FillRectangle(br, rectFull);
					};
				}
				else if (BackgroundColorStyle == BackColorStyle.HorizontalGradient)
				{
					using (LinearGradientBrush lgb = new LinearGradientBrush(
						rectFull, UserBackColor1, UserBackColor2, 0f))
					{
						e.Graphics.FillRectangle(lgb, rectFull);
					};
				}
				else if (BackgroundColorStyle == BackColorStyle.VerticalGradient)
				{
					using (LinearGradientBrush lgb = new LinearGradientBrush(
						rectFull, UserBackColor1, UserBackColor2, 90f))
					{
						e.Graphics.FillRectangle(lgb, rectFull);
					};
				}
				else if (BackgroundColorStyle == BackColorStyle.DiagonalGradient)
				{
					using (LinearGradientBrush lgb = new LinearGradientBrush(
						rectFull, UserBackColor1, UserBackColor2, 45f))
					{
						e.Graphics.FillRectangle(lgb, rectFull);
					};
				}

				#endregion
			} 

			#endregion
			#region Shadow and Foreground Text painting

			//foreground text rendering
			if (TextColorStyle == ForeColorStyle.None)
			{
				using (SolidBrush br = new SolidBrush(this.ForeColor))
				{
					e.Graphics.DrawString(this.Text, this.Font, br, TextLocation);
				};
			}
			else if (TextColorStyle == ForeColorStyle.ForeHorizontalGradient)
			{
				using (LinearGradientBrush br = new LinearGradientBrush(
					new Rectangle(new Point(10, 0), new Size((int)e.Graphics.MeasureString(this.Text, this.Font).Width,
					(int)e.Graphics.MeasureString(this.Text, this.Font).Height)),
					UserForeColor1, UserForeColor2, 0f))
				{
					e.Graphics.DrawString(this.Text, this.Font, br, TextLocation);
				};
			}
			else
			{
				using (LinearGradientBrush br = new LinearGradientBrush(
					new Rectangle(new Point(10, 0), new Size((int)e.Graphics.MeasureString(this.Text, this.Font).Width,
					(int)e.Graphics.MeasureString(this.Text, this.Font).Height)),
					UserForeColor1, UserForeColor2, 90f))
				{
					e.Graphics.DrawString(this.Text, this.Font, br, TextLocation);
				};
			}

			if (Shadow == ShadowStyle.TextShadow || Shadow == ShadowStyle.BothShadows)
			{
				using (SolidBrush br = new SolidBrush(Color.FromArgb(120, this.ShadowColor)))
				{
					e.Graphics.DrawString(this.Text, this.Font, br, new Point(TextLocation.X + ShadowOffset,
						TextLocation.Y + ShadowOffset));
				};
			}

			#endregion
		}

		#endregion
		#region Private methods method

		private GraphicsPath GetPath(Rectangle r)
		{
			GraphicsPath graphPath = new GraphicsPath();

			graphPath.AddLine(0, 0, r.Right, 0);
			graphPath.AddLine(r.Right, 0, r.Right, r.Top);
			graphPath.AddLine(r.Right, r.Top, r.Right, r.Bottom);
			graphPath.AddLine(r.Right, r.Bottom, 0, r.Bottom);
			graphPath.AddLine(0, r.Bottom, 0, 0);

			return graphPath;
		}

		#endregion
	}
}
